﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data;
using System.IO;

namespace AthCommander.Infrastructure
{
    public class CopyHelper
    {
        private ProgressBar _progressBar;

        #region Private Fields
        
        private DataSet _dataCopy;
        private static FileStream _destinationFileStream;
        private int _noOfDirectories;
        private int _noOfFiles;
        private string _currentCopySourceFile;
        private string _currentCopyDestinationFile;
        private string _currentCopyDirectory;
        private long _currentCoppiedSizeOfDirectory;
        private long _currentDirectroyTotalSize;
        private long _totalCopiedSize;
        private long _totalLength;
        private int _damagedAction; 

        #endregion

        public CopyHelper(ProgressBar progressBars)
        {
            _progressBar = progressBars;
            _dataCopy = new DataSet();
        }

        #region Methods

        public void CopyDirectory(DirectoryInfo oldInfo, DirectoryInfo newInfo)
        {
            string sourcePath = oldInfo.FullName;
            string destinationPath = newInfo.FullName;
            string sourceDirectory = oldInfo.FullName;
            string destinationDirectory = newInfo.FullName;

            if (!Directory.Exists(destinationDirectory))
            {
                Directory.CreateDirectory(destinationDirectory);
            }

            Init();
            DirectorySearch(sourceDirectory, "", destinationDirectory);

            if (_dataCopy != null)
            {
                int i = 0;
                for (int EachRecord = 0; EachRecord < _dataCopy.Tables["Copy"].Rows.Count; EachRecord++)
                {
                    if (_dataCopy.Tables["Copy"].Rows[EachRecord]["Type"].ToString() == "DIRECTORY")
                    {
                        i++;
                        ProgressBar(i, _noOfDirectories);
                        DirectoryCreate(_dataCopy.Tables["Copy"].Rows[EachRecord]["Destination"].ToString());
                    }
                }
                i = 0;
                for (int EachRecord = 0; EachRecord < _dataCopy.Tables["Copy"].Rows.Count; EachRecord++)
                {
                    if (_dataCopy.Tables["Copy"].Rows[EachRecord]["Type"].ToString() == "FILE")
                    {
                        i++;
                        ProgressBar(i, _noOfFiles);
                        string strSourceFile = _dataCopy.Tables["Copy"].Rows[EachRecord]["Source"].ToString();
                        string strDestinationFile = _dataCopy.Tables["Copy"].Rows[EachRecord]["Destination"].ToString();
                        System.IO.FileInfo sourceInfo = new FileInfo(strSourceFile);

                        _currentCopySourceFile = strSourceFile;
                        _currentCopyDestinationFile = strDestinationFile;

                        if (_currentCopyDirectory != sourceInfo.DirectoryName)
                        {
                            _currentCopyDirectory = sourceInfo.DirectoryName;
                            _currentCoppiedSizeOfDirectory = 0;
                            _currentDirectroyTotalSize = OneLevelDirectorySize(sourceInfo.Directory);
                        }

                        else
                        {
                            File.Copy(strSourceFile, strDestinationFile);
                        }
                        _currentCoppiedSizeOfDirectory = _currentCoppiedSizeOfDirectory + sourceInfo.Length;
                        _totalCopiedSize = _totalCopiedSize + sourceInfo.Length;
                        UpdatePersentage(_totalCopiedSize, _totalLength);
                    }
                }
            }
        }

        public string CopyFile(FileInfo source, FileInfo destination, FileMode mode)
        {
            int bufferSize = 2000;

            byte[] Readbytes;
            Readbytes = new byte[bufferSize];

            FileStream Sfs = File.OpenRead(source.FullName);
            _destinationFileStream = File.Open(destination.FullName, mode);
            FileInfo Sinfo = new FileInfo(Sfs.Name);
            FileInfo Dinfo = new FileInfo(_destinationFileStream.Name);
            //
            if (Sfs.CanRead && _destinationFileStream.CanWrite)
            {
                while (Sfs.Length - Sfs.Position >= bufferSize)
                {
                    try
                    {
                        Sfs.Read(Readbytes, 0, bufferSize);
                        _destinationFileStream.Write(Readbytes, 0, bufferSize);

                        UpdatePersentage(Sfs.Position, Sfs.Length);
                        System.Windows.Forms.Application.DoEvents();
                    }
                    catch (System.Exception error)
                    {
                        MessageBox.Show(error.Message);
                    }

                }
                if (Sfs.Position < Sfs.Length)
                {
                    Sfs.Read(Readbytes, 0, int.Parse(Sfs.Length.ToString()) - int.Parse(Sfs.Position.ToString()));
                    _destinationFileStream.Write(Readbytes, 0, int.Parse(Sfs.Length.ToString()) - int.Parse(Sfs.Position.ToString()));
                    UpdatePersentage(Sfs.Position, Sfs.Position);
                    _totalCopiedSize += Sfs.Length;

                    System.Windows.Forms.Application.DoEvents();
                }
            }
            try
            {
                Sfs.Close();
                _destinationFileStream.Flush();
                _destinationFileStream.Close();
                _currentCopyDestinationFile = "";
                _currentCopySourceFile = "";
                return "";
            }
            catch (System.Exception error)
            {
                MessageBox.Show("Application closing Files " + error.Message);
                return error.Message;
            }
        }

        #endregion

        #region Private Helpers

        private void Init()
        {
            _noOfFiles = 0;
            _noOfDirectories = 0;
            _dataCopy.Tables.Clear();
            _dataCopy.Tables.Add("Copy");
            _dataCopy.Tables["Copy"].Columns.Add("Type");
            _dataCopy.Tables["Copy"].Columns.Add("Source");
            _dataCopy.Tables["Copy"].Columns.Add("Destination");
            _dataCopy.Tables["Copy"].Columns.Add("Size");
            _dataCopy.Tables["Copy"].Columns.Add("Status");
            _dataCopy.Tables["Copy"].Columns.Add("Comment");
        }

        private void DirectoryCreate(string path)
        {
            try
            {
                if (Directory.Exists(path) == false)
                {
                    Directory.CreateDirectory(path);
                }
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }

        private void DirectorySearch(string strSourceDirectory, string strSourceDirectoryConstant, string strDestinationDirectory)
        {
            _noOfDirectories++;
            string[] strarrDirectoryNames = Directory.GetDirectories(strSourceDirectory);
            string[] strarrFileNames = Directory.GetFiles(strSourceDirectory);
            foreach (string strFileName in strarrFileNames)
            {
                try
                {
                    _noOfFiles++;
                    FileInfo info = new FileInfo(strFileName);
                    long fileLength = info.Length;
                    _totalLength = _totalLength + fileLength;
                    Insert("FILE", strFileName, strSourceDirectoryConstant + @"\" + info.Name, fileLength.ToString(), strDestinationDirectory, "ok", "FileSearch");
                    info = null;

                }
                catch
                {
                }
            }
            foreach (string strDirectoryName in strarrDirectoryNames)
            {
                DirectoryInfo info = new DirectoryInfo(strDirectoryName);
                DirectorySearch(strDirectoryName, strSourceDirectoryConstant + @"\" + info.Name, strDestinationDirectory);
                Insert("DIRECTORY", strDirectoryName, strSourceDirectoryConstant + @"\" + info.Name, "", strDestinationDirectory, "OK", "Dir Search");
                info = null;
            }
        }

        private void Insert(string Type, string Source, string Destination, string Size, string strDestinationDirectory, string status, string Comment)
        {
            try
            {
                DataRow dataRow = _dataCopy.Tables["Copy"].NewRow();
                dataRow["Type"] = Type;
                dataRow["Source"] = Source;
                dataRow["Destination"] = strDestinationDirectory + Destination;
                dataRow["Size"] = Size;
                dataRow["Status"] = status;
                dataRow["Comment"] = Comment;
                _dataCopy.Tables["Copy"].Rows.Add(dataRow);
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message);
            }

        }

        private void UpdatePersentage(long Done, long total)
        {
            try
            {
                decimal persent = decimal.Parse((Done.ToString())) / decimal.Parse(total.ToString()) * 100;
                _progressBar.Value = (int)persent;
                _progressBar.Update();
                _progressBar.Refresh();
            }
            catch (System.Exception error)
            {
                MessageBox.Show(error.Message);
            }
        }

        private long OneLevelDirectorySize(DirectoryInfo directoryInfo)
        {
            long total = 0;
            foreach (FileInfo file in directoryInfo.GetFiles())
            {
                total += file.Length;
            }
            return total;
        }

        private void ProgressBar(int i, int iTotal1)
        {
            int iTotal = iTotal1 / 10;

            for (int Progress = 1; Progress < 11; Progress++)
            {
                if ((iTotal * Progress) == i)
                {
                    break;
                }
            }
        }

        #endregion
    }
}
